/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.ts.controller;

import com.xy.biz.base.domain.resp.ListDictItemResponse;
import com.xy.biz.ts.client.TrainClient;
import com.xy.biz.ts.domain.converter.ExaminationTrainRelConverter;
import com.xy.biz.ts.domain.converter.TrainConverter;
import com.xy.biz.ts.domain.converter.TrainFlowHandleConverter;
import com.xy.biz.ts.domain.converter.TrainUserConverter;
import com.xy.biz.ts.domain.enums.TrainNodeEnum;
import com.xy.biz.ts.domain.enums.TrainPhaseEnum;
import com.xy.biz.ts.domain.query.ExaminationTrainRelQuery;
import com.xy.biz.ts.domain.query.TrainFlowHandleQuery;
import com.xy.biz.ts.domain.query.TrainQuery;
import com.xy.biz.ts.domain.req.*;
import com.xy.biz.ts.domain.resp.*;
import com.xy.biz.ts.service.ExaminationTrainRelService;
import com.xy.biz.ts.service.TrainService;
import com.xy.lang.domain.KeyValue;
import com.xy.lang.domain.Page;
import com.xy.lang.domain.PageRequest;
import com.xy.lang.domain.Result;
import com.xy.lang.validation.SaveChecks;
import com.xy.lang.validation.UpdateChecks;
import com.xy.lang.validation.annotation.Validatable;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 *
 *
 * @author wwj
 * @date 2021-4-1
 */
@Api(tags = "培训")
@Slf4j
@RequestMapping("/api/ts/train")
@RestController
public class TrainController implements TrainClient {

    @Autowired
    private TrainService trainService;
    @Autowired
    private ExaminationTrainRelService examinationTrainRelService;

    @Validatable(groups = {SaveChecks.class})
    @ApiOperation("新建培训")
    @PostMapping(value = "/save")
    public Result<?> saveTrain(@RequestBody SaveTrainRequest request) {
        if (request.getStartTime().toLocalDate().isAfter(request.getEndTime().toLocalDate())) {
            return Result.fail(null, "培训开始时间不能晚于结束时间！");
        }
        if (request.getStartTime().toLocalDate().isBefore(LocalDate.now())) {
            return Result.fail(null, "培训开始时间不能早于当前时间！");
        }
        return trainService.saveTrain(TrainConverter.toBO(request));
    }

    @Validatable
    @ApiOperation("新建培训流程第一次审核")
    @PostMapping(value = "/audit1")
    public Result<?> auditTrain1(@RequestBody HandleTrainFlowRequest request) {
        return trainService.auditTrain1(request);
    }

    @Validatable
    @ApiOperation("新建培训流程第二次审核")
    @PostMapping(value = "/audit2")
    public Result<?> auditTrain2(@RequestBody HandleTrainFlowRequest request) {
        return trainService.auditTrain2(request);
    }

    @ApiOperation("新建培训流程第三次审核")
    @PostMapping(value = "/audit3")
    public Result<?> auditTrain3(@RequestBody HandleTrainFlowRequest request) {
        return trainService.auditTrain3(request);
    }

    @Validatable
    @ApiOperation("新建培训流程终止")
    @PostMapping(value = "/finish_train_flow")
    public Result<?> finishTrainFlow(@RequestBody GetTrainRequest request) {
        return trainService.finishTrainFlow(request);
    }

    @Validatable
    @ApiOperation("培训流程-待办事项")
    @PostMapping(value = "/page_todo")
    public Result<Page<GetTrainResponse>> pageTodoTrainFlow(@RequestBody PageRequest request) {
        TrainFlowHandleQuery trainFlowHandleQuery = TrainFlowHandleConverter.toQuery(request);
        return Result.success(trainService.searchTrainFlowTodo(trainFlowHandleQuery));
    }

    @Validatable(groups = {SaveChecks.class})
    @PostMapping(value = "/save_all")
    public Result<?> saveAllTrain(@RequestBody Collection<SaveTrainRequest> collection) {
        return trainService.saveAllTrain(TrainConverter.toBO(collection));
    }

    @Validatable(groups = {UpdateChecks.class})
    @PostMapping(value = "/update")
    public Result<?> updateTrain(@RequestBody UpdateTrainRequest request) {
        if (request.getStartTime().isAfter(request.getEndTime())) {
            return Result.fail(null, "培训开始时间不能晚于结束时间！");
        }
        if (request.getStartTime().isBefore(LocalDateTime.now())) {
            return Result.fail(null, "培训开始时间不能早于当前时间！");
        }
        return trainService.updateTrain(TrainConverter.toBO(request));
    }

    @Validatable
    @PostMapping(value = "/delete")
    public Result<?> deleteTrain(@RequestBody GetTrainRequest request) {
        return trainService.deleteTrain(request.getTrainId());
    }

    @Validatable
    @PostMapping(value = "/get")
    @Override
    public Result<GetTrainResponse> getTrain(@RequestBody GetTrainRequest request) {
        GetTrainResponse getTrainResponse = TrainConverter.toResponse(trainService.getTrain(request.getTrainId()));
        getTrainResponse.getTrainDocumentRelResponses().stream().peek(t -> {
            t.setId(t.getDocumentId());
            t.setLabel(t.getDocumentName());
        }).collect(Collectors.toList());
        getTrainResponse.getTrainUserResponses().stream().peek(t -> {
            t.setId(t.getUserId());
            t.setLabel(t.getUserName());
        }).collect(Collectors.toList());
        getTrainResponse.getTrainUserGroupResponses().stream().peek(t -> {
            t.setId(t.getUserGroupId());
            t.setLabel(t.getUserGroupName());
        }).collect(Collectors.toList());
        return Result.success(getTrainResponse);
    }

    @PostMapping(value = "/list_by_ids")
    @Override
    public Result<List<GetTrainResponse>> listTrainById(@RequestBody Collection<Long> collection) {
        return Result.success(TrainConverter.toResponse(trainService.listTrainById(collection)));
    }

    @PostMapping(value = "/list_by_flow")
    @Override
    public Result<List<GetTrainResponse>> listTrainByFlow(@RequestBody ListTrainRequest request) {
        return Result.success(trainService.listTrainByFlow(request));
    }

    @Validatable
    @ApiOperation("发起考核")
    @PostMapping(value = "/start_assess")
    public Result<?> startAssess(@RequestBody SaveExaminationTrainRelRequest request) {
        return examinationTrainRelService.saveExaminationTrainRel(request);
    }

    @ApiOperation("在线答题")
    @PostMapping(value = "/page_by_rel")
    public Result<Page<GetExaminationPaperResponse>> pageExaminationPaperByTrainRel(@RequestBody ListExaminationTrainRelRequest request) {
        ExaminationTrainRelQuery query = ExaminationTrainRelConverter.toQuery(request);
        List<GetExaminationPaperResponse> responses = examinationTrainRelService.listExaminationTrainRel(query);
        //通过中间表查询试卷条数
        query.setOffset(0);
        query.setRows(Integer.MAX_VALUE);
        int count = examinationTrainRelService.listExaminationTrainRel(query).size();
        return Result.success(new Page<>(responses, count));
    }

    @ApiOperation("我参与的")
    @PostMapping(value = "/list_participate")
    public Result<List<GetTrainResponse>> listParticipateTrain(@RequestBody ListTrainRequest request) {
        return Result.success((trainService.listParticipantTrain(TrainConverter.toQuery(request))));
    }

//    /**
//     * 我发起的
//     * @return
//     */
//    @PostMapping(value = "/list_my_start")
//    @Deprecated
//    public Result<GetTrainByClassifyResponse> listMyStartTrain() {
//        return Result.success(trainService.listMyStartTrain());
//    }

    @PostMapping(value = "/count")
    @Override
    public Result<Integer> countTrain(@RequestBody ListTrainRequest request) {
        return Result.success(trainService.countTrain(TrainConverter.toQuery(request)));
    }

    @PostMapping(value = "/page")
    @Override
    public Result<Page<GetTrainResponse>> pageTrain(@RequestBody ListTrainRequest request) {
        TrainQuery query = TrainConverter.toQuery(request);
        List<GetTrainResponse> list = TrainConverter.toResponse(trainService.listTrain(query));
        int count = trainService.countTrain(query);
        return Result.success(new Page<>(list, count));
    }

    @PostMapping(value = "/list_practical_operation")
    public Result<List<GetTrainResponse>> listPracticalOperation(@RequestBody ListTrainRequest request) {
        TrainQuery query = TrainConverter.toQuery(request);
        return Result.success(TrainConverter.toResponse(trainService.listPracticalOperation(query)));
    }

    @PostMapping(value = "/participate")
    public Result<Page<GetTrainResponse>> pageParticipateTrain(@RequestBody ListTrainRequest request) {
        TrainQuery query = TrainConverter.toQuery(request);
        List<GetTrainResponse> list = TrainConverter.toResponse(trainService.listTrain(query));
        int count = trainService.countTrain(query);
        return Result.success(new Page<>(list, count));
    }

    @ApiOperation("获取培训分类")
    @PostMapping(value = "/list_train_classify")
    public Result<List<KeyValue>> listTrainClassify() {
        return Result.success(trainService.listTrainClassify());
    }

    @ApiOperation("获取培训分类下的培训列表")
    @PostMapping(value = "/list_train_by_classify")
    public Result<List<GetTrainResponse>> listTrainByClassify(@RequestBody ListTrainRequest request) {
        List<GetTrainResponse> getTrainResponses = trainService.listTrainByClassify(TrainConverter.toQuery(request));
        return Result.success(getTrainResponses);
    }

    @ApiOperation("获取单个培训下的记录")
    @PostMapping(value = "/list_record_by_train")
    public Result<List<GetTrainUserResponse>> listRecordByTrain(@RequestBody ListRecordByTrainRequest request) {
        return Result.success(TrainUserConverter.toResponse(trainService.listRecordByTrain(TrainConverter.toQuery(request))));
    }

    @ApiOperation("我培训的")
    @PostMapping(value = "/list_my_training")
    public Result<List<GetTrainResponse>> listMyTraining(@RequestBody ListTrainRequest request) {
        List<GetTrainResponse> getTrainResponses = trainService.listMyTraining(TrainConverter.toQuery(request));
        return Result.success(getTrainResponses);
    }

    @ApiOperation("获取培训发放人列表")
    @Validatable
    @PostMapping(value = "/list_release_user_by_train")
    public Result<List<GetTrainUserResponse>> listReleaseUserByTrain(@RequestBody GetUserByTrainRequest request) {
        return Result.success(trainService.listReleaseUserByTrain(TrainConverter.toQuery(request)));
    }

    @ApiOperation("提醒考试")
    @PostMapping(value = "/remind_test")
    public Result<?> remindTest(@RequestBody SendToUserRequest request) {
        return Result.success(trainService.remindTest(request));
    }

    @ApiOperation("获取培训节点信息")
    @GetMapping(value = "/list_pre_options")
    public Result<Map<String, List>> listPreOptions() {
        Map<String, List> map = new HashMap<>(4);
        map.put("trainNode", listStatus());
        map.put("phase", listPhase());
        return Result.success(map);
    }

    private List<KeyValue<Integer, String>> listStatus() {
        TrainNodeEnum[] enums = TrainNodeEnum.values();
        List<KeyValue<Integer, String>> list = new ArrayList<>();
        for (TrainNodeEnum e : enums) {
            list.add(e.toKeyValue());
        }
        return list;
    }

    private List<KeyValue<String, String>> listPhase() {
        TrainPhaseEnum[] enums = TrainPhaseEnum.values();
        List<KeyValue<String, String>> list = new ArrayList<>();
        for (TrainPhaseEnum e : enums) {
            list.add(e.toKeyValue());
        }
        return list;
    }
}
